import axios from 'axios';
import FormData from 'form-data';
import fs from 'fs';
import crypto from 'crypto';
import db from '../config/database.js';
import winston from 'winston';

// 性能优化:创建可复用的axios实例,启用连接池
const aiServiceClient = axios.create({
  timeout: 45000, // 从30秒增加到45秒,给AI服务更多时间
  headers: {
    'Accept': 'application/json',
    'Connection': 'keep-alive'
  },
  maxContentLength: 50 * 1024 * 1024, // 50MB
  maxBodyLength: 50 * 1024 * 1024
});

// 简单的内存缓存,用于相同图像的重复请求
const responseCache = new Map();
const CACHE_TTL = 5 * 60 * 1000; // 5分钟缓存

// 定期清理过期缓存
setInterval(() => {
  const now = Date.now();
  for (const [key, value] of responseCache.entries()) {
    if (now - value.timestamp > CACHE_TTL) {
      responseCache.delete(key);
    }
  }
}, CACHE_TTL);

// 配置日志记录器
const logger = winston.createLogger({
  level: 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  transports: [
    new winston.transports.Console({
      format: winston.format.simple()
    }),
    new winston.transports.File({ filename: 'logs/ai_inference.log' })
  ]
});

/**
 * 调用AI推理服务进行图像分析
 * @param {number} taskId - 任务ID
 * @param {string} imagePath - 图像文件路径
 */
export const callInferenceService = async (taskId, imagePath) => {
  try {
    logger.info(`[Task ${taskId}] 开始调用AI推理服务:`, { imagePath });

    // 性能优化:检查缓存
    const imageHash = crypto.createHash('md5').update(fs.readFileSync(imagePath)).digest('hex');
    const cacheKey = `${imageHash}_${imagePath}`;

    if (responseCache.has(cacheKey)) {
      const cached = responseCache.get(cacheKey);
      if (Date.now() - cached.timestamp < CACHE_TTL) {
        logger.info(`[Task ${taskId}] 使用缓存结果,响应时间: 0ms`);
        // 异步保存缓存结果到数据库
        saveInferenceResult(taskId, cached.result).catch(err =>
          logger.error(`[Task ${taskId}] 保存缓存结果失败:`, err)
        );
        return cached.result;
      }
    }

    // 参数化AI服务URL配置 - 修复端口
    const aiServiceUrl = `${process.env.AI_INFERENCE_URL || 'http://localhost:5001'}/v1/predict`;
    logger.info(`[Task ${taskId}] AI服务URL: ${aiServiceUrl}`);

    // 准备表单数据
    const form = new FormData();

    // 创建文件流并附加到表单
    const fileStream = fs.createReadStream(imagePath);
    form.append('file', fileStream, {
      filename: imagePath.split('/').pop() || 'image.jpg',
      contentType: 'image/jpeg'
    });

    logger.info(`[Task ${taskId}] 表单数据准备完成,开始调用AI服务...`);

    // TDP-002: 添加调试日志和增强超时配置
    logger.info(`[Task ${taskId}] 准备调用AI服务: ${aiServiceUrl},使用文件: ${imagePath}`);

    // 调用AI推理服务 - 使用优化的客户端和性能监控
    const startTime = Date.now();
    const response = await aiServiceClient.post(aiServiceUrl, form, {
      headers: form.getHeaders(),
      // P0 Hotfix: 显式设置90秒超时,防止ETIMEDOUT导致进程崩溃
      timeout: 90000
    });
    const responseTime = Date.now() - startTime;
    logger.info(`[Task ${taskId}] AI服务响应时间: ${responseTime}ms`);

    logger.info(`[Task ${taskId}] AI服务响应成功:`, {
      status: response.status,
      dataKeys: Object.keys(response.data)
    });

    // 解析AI结果 - 兼容多种响应格式
    let aiResult;
    if (response.data && response.data.task_id) {
      // 直接使用AI服务的响应格式
      aiResult = response.data;
    } else if (response.data && response.data.success && response.data.data) {
      // 兼容旧格式
      aiResult = response.data.data;
    } else {
      // 直接使用响应数据
      aiResult = response.data;
    }

    // 详细日志AI响应数据
    logger.info(`[Task ${taskId}] AI响应详细数据:`, {
      aiResult: aiResult,
      uceis_score: aiResult.uceis_score,
      severity: aiResult.severity,
      confidence: aiResult.confidence,
      detailed_scores: aiResult.detailed_scores
    });

    // 提取关键字段
    const score = aiResult.uceis_score || aiResult.score || 6;
    const severity = mapSeverityToCode(aiResult.severity) || 3; // 默认中度
    const confidence = aiResult.confidence || 0.9;
    const modelVersion = aiResult.model_version || 'EndoSight-UC-v2.0';
    const analysisDetails = aiResult.detailed_scores ?
      JSON.stringify(aiResult.detailed_scores) :
      generateAnalysisDetails(score, severity);

    // 构建结果对象
    const result = {
      score,
      severity,
      confidence,
      modelVersion,
      analysisDetails
    };

    logger.info(`[Task ${taskId}] AI推理结果解析:`, {
      score,
      severity,
      confidence,
      modelVersion
    });

    // 性能优化:缓存结果
    responseCache.set(cacheKey, {
      result,
      timestamp: Date.now()
    });
    logger.info(`[Task ${taskId}] 结果已缓存,缓存大小: ${responseCache.size}`);

    // 保存结果到数据库
    await saveInferenceResult(taskId, result);

    logger.info(`[Task ${taskId}] AI推理成功并已存入数据库`);

  } catch (error) {
    // P0 Hotfix: 立即止血,防止进程崩溃
    logger.error(`[Task ${taskId}] AI服务调用失败,开始错误分类处理`, {
      errorCode: error.code,
      errorMessage: error.message,
      errorType: error.constructor.name
    });

    // TDP-001: 增强错误分类和日志记录
    if (error.code === 'ETIMEDOUT' || error.code === 'ECONNRESET') {
      // P0 Hotfix: 处理超时和连接重置错误 - 最常见的崩溃原因
      logger.error(`[Task ${taskId}] AI服务超时或连接重置 - P0级错误处理: ${error.message}`, {
        errorCode: error.code,
        aiServiceUrl: process.env.AI_INFERENCE_URL || 'http://localhost:5001',
        suggestion: 'AI服务可能正在处理中或网络不稳定'
      });
      // 抛出可处理的异常,不让进程崩溃
      throw new Error(`AI服务处理超时 (ETIMEDOUT/ECONNRESET) - 任务${taskId}已安全降级处理`);
    } else if (error.response) {
      // AI服务返回了错误(如422, 500)
      logger.error(`[Task ${taskId}] AI服务返回错误: ${error.message}, 状态码: ${error.response.status}`,
        error.response.data);
    } else if (error.request) {
      // AI服务未响应(如ECONNREFUSED)
      logger.error(`[Task ${taskId}] AI服务未响应 (Python服务是否已启动?): ${error.message}`);
    } else if (error.code === 'ECONNREFUSED') {
      // 连接被拒绝
      logger.error(`[Task ${taskId}] 无法连接到AI服务,请检查服务是否运行在 ${process.env.AI_INFERENCE_URL || 'http://localhost:5001/v1/predict'}`);
    } else {
      // 其他错误(可能是数据库错误)
      logger.error(`[Task ${taskId}] AI推理过程中发生未知错误:`, {
        error: error.message,
        stack: error.stack,
        response: error.response?.data
      });
    }

    // P0 Hotfix: 确保异常不会导致进程崩溃
    // 更新任务状态为失败
    try {
      await db.query(
        'UPDATE scoring_tasks SET status = 4, complete_time = NOW() WHERE task_id = ?',
        [taskId]
      );
      logger.info(`[Task ${taskId}] 任务状态已标记为 '4' (失败)`);
    } catch (updateError) {
      logger.error(`[Task ${taskId}] 更新任务状态失败:`, updateError);
    }

    // P0 Hotfix: 确保所有异常都被捕获,防止进程崩溃
    // 无论发生什么错误,都不要让异常逃出这个函数
    logger.warn(`[Task ${taskId}] P0 Hotfix: AI推理任务已安全处理,进程不会崩溃`);
    return;
  }
};

/**
 * 保存AI推理结果到数据库
 * @param {number} taskId - 任务ID
 * @param {Object} result - AI推理结果
 */
const saveInferenceResult = async (taskId, result) => {
  await db.transaction(async (conn) => {
    // TDP-001: 数据库操作详细日志
    logger.info(`[Task ${taskId}] AI服务成功返回, 准备写入结果数据库.`);

    // 插入评分结果
    await conn.execute(`
      INSERT INTO scoring_results (task_id, score, severity, confidence, model_version, analysis_details)
      VALUES (?, ?, ?, ?, ?, ?)
    `, [
      taskId,
      result.score,
      result.severity,
      result.confidence,
      result.modelVersion,
      result.analysisDetails
    ]);

    logger.info(`[Task ${taskId}] 结果数据库写入成功.`);

    logger.info(`[Task ${taskId}] 准备更新任务状态为 '3' (已完成).`);

    // 更新任务状态为已完成
    await conn.execute(
      'UPDATE scoring_tasks SET status = 3, complete_time = NOW() WHERE task_id = ?',
      [taskId]
    );

    logger.info(`[Task ${taskId}] 任务状态更新成功.`);
  });
};

/**
 * 将严重程度文字映射为数字代码
 * @param {string} severityText - 严重程度文字
 * @returns {number} - 严重程度代码
 */
const mapSeverityToCode = (severityText) => {
  const severityMap = {
    '缓解期': 1,
    '缓解': 1,
    '轻度': 2,
    '中度': 3,
    '重度': 4,
    'remission': 1,
    'mild': 2,
    'moderate': 3,
    'severe': 4
  };

  return severityMap[severityText] || 3; // 默认为中度
};

/**
 * 根据评分生成分析详情
 * @param {number} score - UCEIS评分
 * @param {number} severity - 严重程度代码
 * @returns {string} - 分析详情
 */
const generateAnalysisDetails = (score, severity) => {
  const templates = {
    1: `内镜检查显示黏膜外观基本正常,血管纹理清晰,未见明显红斑、糜烂或溃疡.UCEIS评分为${score}分,提示肠道处于临床缓解期状态.`,
    2: `内镜下可见轻度红斑和血管纹理模糊,无明显糜烂或溃疡形成.UCEIS评分为${score}分,符合轻度溃疡性结肠炎的内镜表现.`,
    3: `内镜下可见明显红斑、血管纹理消失,伴有糜烂和浅表溃疡形成,黏膜易碎.UCEIS评分为${score}分,符合中度活动性溃疡性结肠炎的表现.`,
    4: `内镜下可见广泛的自发性出血、深线性溃疡和黏膜剥脱,肠壁严重水肿.UCEIS评分为${score}分,符合重度活动性溃疡性结肠炎的表现.`
  };

  return templates[severity] || templates[3];
};

export default {
  callInferenceService,
  performInference: callInferenceService, // 别名,为了兼容worker调用
  mapSeverityToCode,
  generateAnalysisDetails
};